package com.lslk.othello.helpers;

import android.util.Log;

import com.lslk.othello.models.Game;
import com.lslk.othello.models.Position;
import com.lslk.othello.models.Position.Occupation;

public class GameFunctions {
	private static final String TAG = "GameFunctions";
	/**
	 * Return if the position is legal
	 * 
	 * @param g
	 * @param pos
	 * @return
	 */
	public static boolean isLegal(final Game g,final int pos) {
		//The reason that everything is calculated in the run time is that 
		//Android platform runs faster with Local Variables.
		//If i create an array of elements that does this, it will prob be slower.
		
		int same=(g.blackTurn) ? Occupation.BLACK : Occupation.WHITE;
		//Log.i(TAG,""+pos);
		boolean r=false;
		int i,end,counter,occ,empty=Occupation.EMPTY;
		Position[] pieces=g.positions;
		if(pieces[pos].occupation!=empty)
			return false;
		//Check Horizontal Left;
		counter=0;
		end=pos-pos%8;
		for(i=pos-1;i>=end;i--){
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				if(counter==0)
					break;
				else{
					r=true;
				}
			}else
				counter++;
		}
		if(r)
			return r;
		//Check Horizontal Right;
		counter=0;
		end=pos+(8-pos%8);
		for(i=pos+1;i<end;i++){
			//Log.i(TAG,"Horizontal Right: "+pos+"| "+i+" , "+end);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				if(counter==0)
					break;
				else{
					r=true;
				}
			}else
				counter++;
		}
		if(r)
			return r;
		//Check Vertical Up;
		counter=0;
		end=pos%8;
		for(i=pos-8;i>=end;i-=8){
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				if(counter==0)
					break;
				else{
					r=true;
				}
			}else
				counter++;
		}
		if(r)
			return r;
		//Check Vertical Down;
		counter=0;
		end=56+pos%8;
		for(i=pos+8;i<=end;i+=8){
			//Log.i(TAG,"Vertical Down: "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				if(counter==0)
					break;
				else{
					r=true;
				}
			}else
				counter++;
		}
		if(r)
			return r;
		//Check Upper Left;
		counter=0;
		if(pos%8!=0)
		for(i=pos-9;(i>=0);i-=9){
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				//Log.i(TAG,"Pos/i/counter: "+pos+"/"+i+"/"+counter);
				if(counter==0)
					break;
				else{
					r=true;
				}
			}else
				counter++;
			if(i%8==0)
				break;
		}
		if(r)
			return r;
		//Check Upper Right;
		counter=0;
		if(pos%8!=7)
		for(i=pos-7;(i>0);i-=7){
			//if(g.blackTurn)
			//Log.i(TAG,"Upper Right: "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				//Log.i(TAG,"Same! "+same+" counter: "+counter);
				if(counter==0)
					break;
				else{
					r=true;
				}
			}else
				counter++;
			if(i%8==7)
				break;
		}
		if(r)
			return r;
		//Check Down Left;
		counter=0;
		if(pos%8!=0)
		for(i=pos+7;(i<63);i+=7){
			//if(g.blackTurn)
				//Log.i(TAG,"Down Left"+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				if(counter==0)
					break;
				else{
					r=true;
				}
			}else
				counter++;
			if(i%8==0)
				break;
		}
		if(r)
			return r;
		//Check Down Right;
		counter=0;
		if(pos%8!=7)
		for(i=pos+9;(i<=63);i+=9){
			occ=pieces[i].occupation;
			if(occ==empty)
				break;	
			if(occ==same){
				if(counter==0)
					break;
				else{
					r=true;
				}
			}else
				counter++;
			if(i%8==7)
				break;
		}
		return r;
	}
	/**
	 * Process move at pos in game g;
	 * @param g
	 * @param pos
	 */
	public static void process_move(final Game g,final int pos){
		Log.i(TAG,"Process last move: "+pos);
		Position[] pieces=g.positions;
		int same=(g.blackTurn) ? Occupation.BLACK : Occupation.WHITE;
		int i,end,counter,occ,empty=Occupation.EMPTY;
		boolean canTurn;
		final int[] turns=new int[8];
		canTurn=false;
		counter=0;
		end=pos-pos%8;
		for(i=pos-1;i>=end;i--){
			//Log.i(TAG,"Horizontal Left "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				canTurn=true;
				break;
			}else{
				turns[counter]=i;
				counter++;
			}
		}	
		if(canTurn)
			for(i=0;i<counter;i++)
				pieces[turns[i]].makeOpposite();
		//Check Horizontal Right;
		canTurn=false;
		counter=0;
		end=pos+(8-pos%8);
		for(i=pos+1;i<end;i++){
			//Log.i(TAG,"Horizontal Right "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				canTurn=true;
				break;
			}else{
				//Log.i(TAG,"Recorded: "+i+" counter:"+ (counter+1));
				turns[counter]=i;
				counter++;
			}
		}	
		
		if(canTurn)
			for(i=0;i<counter;i++)
				pieces[turns[i]].makeOpposite();
		//Check Vertical Up;
		canTurn=false;
		counter=0;
		end=pos%8;
		for(i=pos-8;i>=end;i-=8){
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				canTurn=true;
				break;
			}else{
				turns[counter]=i;
				counter++;
			}
		}	
		if(canTurn)
			for(i=0;i<counter;i++)
				pieces[turns[i]].makeOpposite();
		//Check Vertical Down;
		canTurn=false;
		counter=0;
		end=56+pos%8;
		for(i=pos+8;i<=end;i+=8){
			//Log.i(TAG,"Vertical Down "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				canTurn=true;
				break;
			}else{
				turns[counter]=i;
				counter++;
			}
		}	
		if(canTurn)
			for(i=0;i<counter;i++)
				pieces[turns[i]].makeOpposite();
		//Check Upper Left;
		canTurn=false;
		counter=0;
		if(pos%8!=0)
		for(i=pos-9;(i>=0);i-=9){
			//Log.i(TAG,"Upper Left "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				canTurn=true;
				break;
			}else{
				turns[counter]=i;
				counter++;
			}
			if(i%8==0)
				break;
		}	
		if(canTurn)
			for(i=0;i<counter;i++)
				pieces[turns[i]].makeOpposite();
		//Check Upper Right;
		canTurn=false;
		counter=0;
		if(pos%8!=7)
		for(i=pos-7;(i>0);i-=7){
			//Log.i(TAG,"Upper Right "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				canTurn=true;
				break;
			}else{
				turns[counter]=i;
				counter++;
			}
			 if(i%8==7)
				 break;
		}	
		if(canTurn)
			for(i=0;i<counter;i++)
				pieces[turns[i]].makeOpposite();	
		//Check Down Left;
		canTurn=false;
		counter=0;
		if(pos%8!=0)
		for(i=pos+7;(i<63);i+=7){
			//Log.i(TAG,"Down Left "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				canTurn=true;
				break;
			}else{
				turns[counter]=i;
				counter++;
			}
			if(i%8==0)
				break;
		}	
		if(canTurn)
			for(i=0;i<counter;i++)
				pieces[turns[i]].makeOpposite();
		//Check Down Right;
		canTurn=false;
		counter=0;
		if(pos%8!=7)
		for(i=pos+9;(i<=63);i+=9){
			//Log.i(TAG,"Down Right "+i);
			occ=pieces[i].occupation;
			if(occ==empty)
				break;
			if(occ==same){
				canTurn=true;
				break;
			}else{
				turns[counter]=i;
				counter++;
			}
			 if(i%8==7)
				 break;
		}	
		if(canTurn)
			for(i=0;i<counter;i++)
				pieces[turns[i]].makeOpposite();
	}
	public static int[] finalCount(final Game g){
		int black=0,white=0;
		final int isWhite=Occupation.WHITE,isBlack=Occupation.BLACK;
		for(Position p:g.positions){
			switch(p.occupation){
				case isWhite: white++; break;
				case isBlack: black++; break;
			}
		}
		return new int[]{0,white,black};
	}
	/**
	 * Check if game is over and announce the winner.
	 * @param g
	 */
	public static int isOver(final Game g){
		int black=0,white=0;
		final int isWhite=Occupation.WHITE,isBlack=Occupation.BLACK;
		for(Position p:g.positions){
			switch(p.occupation){
				case isWhite: white++; break;
				case isBlack: black++; break;
			}
		}
		if(black==0)
			return Result.WHITE_WIN;
		if(white==0)
			return Result.BLACK_WIN;
		if( (black+white)>=64 || g.skiped==1){
			if(black>white)
				return Result.BLACK_WIN;
			if(black==white)
				return Result.TIE;
			return Result.WHITE_WIN;
		}
		return Result.NOT_OVER;
	}
	public interface Result{
		public static final int NOT_OVER=0;
		public static final int TIE=1;
		public static final int WHITE_WIN=2;
		public static final int BLACK_WIN=3;
	}
}
